
package cz.muni.fi.pa165.hauntedhouses.web;

import cz.muni.fi.pa165.hauntedhouses.dto.AbilityDTO;
import cz.muni.fi.pa165.hauntedhouses.dto.GhostDTO;
import cz.muni.fi.pa165.hauntedhouses.facade.ServiceFacade;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.Before;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Siliarus
 */
@UrlBinding("/jsp/admin/ghosts")
public class AdminGhostsActionBean implements ActionBean {

    final static Logger log = LoggerFactory.getLogger(GhostsActionBean.class);
    private ActionBeanContext context;
    @SpringBean
    protected ServiceFacade sf;

    
    public Resolution adminGhosts() {
        return new ForwardResolution("/WEB-INF/jsp/admin/adminGhosts.jsp");
    }
    
    @DefaultHandler
    public Resolution home() {
        return new ForwardResolution("/WEB-INF/jsp/admin/adminHome.jsp");
    }
    
    public Resolution adminHouses() {
        return new ForwardResolution("/WEB-INF/jsp/admin/houses.jsp");
    }
    
    public Resolution adminAbilities() {
        return new ForwardResolution("/WEB-INF/jsp/admin/abilities.jsp");
    }

    public List<AbilityDTO> getAbilities() {
        loadGhostFromDatabase();
        return ghost.getAbilities();
    }

    public List<GhostDTO> getGhosts() {
        return sf.findAllGhosts();
    }
    @ValidateNestedProperties(value = {
        @Validate(on = {"add", "save"}, field = "name", required = true),
        @Validate(on = {"add", "save"}, field = "abilityType", required = true),
        @Validate(on = {"add", "save"}, field = "description", required = true)
    })
    private GhostDTO ghost;

    public Resolution add() {
        log.debug("add() ghost={}", ghost);
        ghost.setLastHaunted(new Date());
        ghost.setAbilities(new ArrayList<AbilityDTO>());
        switch (ghost.getLvl()) {
            case 1:
                ghost.setExperience(0);
                break;
            case 2:
                ghost.setExperience(10);
                break;
            case 3:
                ghost.setExperience(25);
                break;
            case 4:
                ghost.setExperience(50);
                break;
            case 5:
                ghost.setExperience(100);
                break;
            case 6:
                ghost.setExperience(200);
                break;

        }
        sf.createGhost(ghost);
        return new RedirectResolution(this.getClass(), "adminGhosts");
    }

    public GhostDTO getGhost() {
        return ghost;
    }

    public void setGhost(GhostDTO ghost) {
        this.ghost = ghost;
    }

    public Resolution delete() {
        log.debug("delete({})", ghost.getId());
        sf.removeGhost(ghost);
        return new RedirectResolution(this.getClass(), "adminGhosts");
    }
    private AbilityDTO ability;
    
    @Before(stages = LifecycleStage.BindingAndValidation, on = {"deleteAbility"})
    public void loadAbilityFromDatabase() {
        String ids = context.getRequest().getParameter("ability.id");
        if (ids == null) {
            return;
        }
        ability = sf.getAbility(Long.parseLong(ids));
    }
    
    public Resolution deleteAbility() {
        loadAbilityFromDatabase();
        
        log.debug("delete({})", ghost.getId());
        sf.removeAbilityFromGhost(ghost, ability);
        return new ForwardResolution("/WEB-INF/jsp/admin/addAbilitiesToGhost.jsp");
    }

    @Before(stages = LifecycleStage.BindingAndValidation, on = {"edit", "save", "delete", "getAbilities", "getAvailableAbilities", "addAbilityToGhost", "getAvailableAbilities","deleteAbility"})
    public void loadGhostFromDatabase() {
        String ids = context.getRequest().getParameter("ghost.id");
        if (ids == null) {
            return;
        }
        ghost = sf.getGhost(Long.parseLong(ids));
    }

    @Before(stages = LifecycleStage.BindingAndValidation, on = {"save"})
    public void loadLevelFromDatabase() {
        String ids = context.getRequest().getParameter("ghost.id");
        if (ids == null) {
            return;
        }
        ghost = sf.getGhost(Long.parseLong(ids));
        currentLevel = ghost.getLvl();
    }
    Integer currentLevel = null;

    public Resolution edit() {
        log.debug("edit() ghost={}", ghost);
        return new ForwardResolution("/WEB-INF/jsp/admin/adminGhostEdit.jsp");
    }

    public Resolution save() {
        log.debug("save() ghost={}", ghost);
        if (currentLevel != null && ghost.getLvl() != currentLevel) {
            switch (ghost.getLvl()) {
                case 1:
                    ghost.setExperience(0);
                    break;
                case 2:
                    ghost.setExperience(10);
                    break;
                case 3:
                    ghost.setExperience(25);
                    break;
                case 4:
                    ghost.setExperience(50);
                    break;
                case 5:
                    ghost.setExperience(100);
                    break;
                case 6:
                    ghost.setExperience(200);
                    break;

            }
        }
        sf.updateGhost(ghost);
        return new RedirectResolution(this.getClass(), "adminGhosts");
    }

    public Resolution storno() {
        log.debug("storno() ghost={}", ghost);
        return new RedirectResolution(this.getClass(), "adminGhosts");
    }

    public Resolution manageAbilities() {
        log.debug("manageAbilities() ghost={}", ghost);
        return new ForwardResolution("/WEB-INF/jsp/admin/addAbilitiesToGhost.jsp");
    }

    public List<AbilityDTO> getAvailableAbilities() {
        List<AbilityDTO> abilities = new ArrayList<AbilityDTO>();
        List<AbilityDTO> abilitiesByType = new ArrayList<AbilityDTO>();
        int lvl = ghost.getLvl();
        
        for(AbilityDTO a : sf.findAbilitiesByType(ghost.getAbilityType())) {
            abilitiesByType.add(a);
        }
        
        for(AbilityDTO a : ghost.getAbilities()) {
            abilitiesByType.remove(a);
        }
        
        for(AbilityDTO a : abilitiesByType) {
            
            if(lvl <= 2) {
                if(a.getAbilityLevel() == 1) {
                    abilities.add(a);
                }
            } else if(lvl <= 5) {
                if(a.getAbilityLevel() <= 2) {
                    abilities.add(a);
                }
            } else if(lvl <= 6){
                if(a.getAbilityLevel() <= 3) {
                    abilities.add(a);
                }
            }
        }
        return abilities;
    }

    @Override
    public void setContext(ActionBeanContext context) {
        this.context = context;
    }

    @Override
    public ActionBeanContext getContext() {
        return context;
    }
    private Long selectedAbility;

    public Long getSelectedAbility() {
        return selectedAbility;
    }

    public void setSelectedAbility(Long selected) {
        this.selectedAbility = selected;
    }

    public Resolution addAbilityToGhost() {
        log.debug("addAbilityToGhost() ability={}", selectedAbility);
        if(selectedAbility != null) {
            List<AbilityDTO> abilities = ghost.getAbilities();
            if(abilities.isEmpty()) { 
                abilities.add(sf.getAbility(selectedAbility));
            } else {
            
            int level = sf.getAbility(selectedAbility).getAbilityLevel();
            if(!abilities.contains(sf.getAbility(selectedAbility))) {
                
                AbilityDTO abilityWithLevelX = null;
                for(AbilityDTO a : abilities) {
                    if(a.getAbilityLevel() == level) {
                        abilityWithLevelX = a;
                        break;
                    }
                }
                
                if(abilityWithLevelX != null) {
                    abilities.remove(abilityWithLevelX);
                }
            
                abilities.add(sf.getAbility(selectedAbility));
            }
            }
            ghost.setAbilities(abilities);
            sf.updateGhost(ghost);  
        }
        return new ForwardResolution("/WEB-INF/jsp/admin/addAbilitiesToGhost.jsp");
    }
}
